/*
 * TestM.nc -- main test application source file
 *
 * Copyright (C) Andrey Vihrov <andrey.vihrov@gmail.com>, 2010
 * Copyright (C) Askar Salimbaev <ghostinshell@gmail.com>, 2010
 *
 * This file is part of Intermote.
 *
 * Intermote is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Intermote is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Intermote.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>

module TestM @safe()
{
	uses {
		interface Boot;
		interface Leds;

		interface SplitControl as SerialControl;
		interface Packet as SerialPacket;
		interface AMSend as SerialSend;

		interface SplitControl as IMControl;
		interface Intermote;
	}
}
implementation
{
	#define BUFLEN 16

	enum {
		S_INIT,
		S_WRITE,
		S_WRITEFAIL,
		S_READ,
		S_END
	} state;

	const char wbuf[BUFLEN] = "zomgzomgzomgzom";
	char rbuf[BUFLEN];

	message_t packet;


	void print (int st, const char *s) {
		size_t len = strlen(s) + 1;
		char *payload;

		state = st;

		call SerialPacket.clear(&packet);
		payload = call SerialPacket.getPayload(&packet, len);
		if (!payload)
			return;

		strcpy(payload, s);

		call SerialSend.send(AM_BROADCAST_ADDR, &packet, len);
	}

	event void Boot.booted (void) {
		call Leds.led2Toggle();
		call SerialControl.start();
	}

	event void SerialControl.startDone (error_t err) {
		if (err == SUCCESS)
			call IMControl.start();
	}

	event void IMControl.startDone (error_t err) {
		if (err == SUCCESS)
			print(S_INIT, "Initialization complete");
		else
			print(S_END, "Initialization failed");
	}

	event void Intermote.writeDone (error_t err, size_t count) {
		static unsigned long counter;
		static char buf[20];

		if (err == SUCCESS && count == BUFLEN) {
			if (++counter % 256 != 0)
				call Intermote.write(wbuf, BUFLEN);
			else {
				sprintf(buf, "Wrote %luK...", counter / 64);
				print(S_WRITE, buf);
			}

		} else {
			print(S_WRITEFAIL, "Write failed");
		}
	}

	event void Intermote.readDone (error_t err, size_t count) {
		static unsigned long counter;
		static char buf[20];

		if (err == SUCCESS && count == BUFLEN && !memcmp(rbuf, wbuf, BUFLEN)) {
			if (++counter % 256 != 0)
				call Intermote.read(rbuf, BUFLEN);
			else {
				sprintf(buf, "Read %luK...", counter / 64);
				print(S_READ, buf);
			}
		} else {
			if (err == SUCCESS && count == 0)
				print(S_END, "Read failed: end of file");
			else
				print(S_END, "Read failed");
		}
	}

	event void SerialSend.sendDone (message_t *msg, error_t err) {
		if (msg == &packet) {
			switch (state) {
				case S_INIT:
					call Leds.led2Toggle();
					if (TOS_NODE_ID == 1)
						call Intermote.write(wbuf, BUFLEN);
					break;

				case S_WRITE:
					call Intermote.write(wbuf, BUFLEN);
					break;

				case S_WRITEFAIL:
					print(S_READ, "Starting read from offset 0");
					break;

				case S_READ:
					call Intermote.read(rbuf, BUFLEN);
					break;

				case S_END:

					break;
			}
		}
	}


	event void SerialControl.stopDone (error_t err) { }
	event void IMControl.stopDone (error_t err) { }
	event void Intermote.openDone (error_t err) { }
	event void Intermote.rseekDone (error_t err) { }
	event void Intermote.dropDone (error_t err) { }
}
